package control;

import java.awt.FontFormatException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import model.Album;
import model.Artista;
import model.Musica;
import model.Usuario;
import static view.InterfacePesquisarMusica.isInteger;

public class Controle {
        
    //public void executar();
        
    public static Usuario usuarioAtual = null;
    public static ArrayList<Usuario> usuariosDoSistema = new ArrayList();
    
    /**
     * Requere uma entrada não nula de dados do usuário
     * @param mensagem mensagem a ser disposta para o usuário
     * @param titulo titulo de escopo da mensagem 
     * @return 
     */
    public static String getInput(String mensagem, String titulo){
        String retorno;
        do{
            retorno = JOptionPane.showInputDialog(null, mensagem, titulo, JOptionPane.PLAIN_MESSAGE);
        } while (retorno == null);
    
        return retorno;
    }
    
    /**
     * Requere uma entrada não nula de dados do usuário, dentro de uma das opções dispostas (dropList/ComboBox)
     * @param mensagem mensagem a ser disposta para o usuário
     * @param titulo de escopo da mensagem 
     * @param opcoes lista de opções entre as quais o usuário irá selecionar
     * @return 
     */
    public static String getInput(String mensagem, String titulo, Object[] opcoes){
        String retorno;
        do{
            retorno = (String) JOptionPane.showInputDialog(null, mensagem, titulo, 
                                                         JOptionPane.PLAIN_MESSAGE, null, opcoes, "");
        } while (retorno == null);
    
        return retorno;
    }
    
    /**
     * Requere uma entrada não nula e númerica de dados do usuário
     * @param mensagem mensagem a ser disposta para o usuário
     * @param titulo titulo de escopo da mensagem 
     * @return 
     */
    public static int getInputNum(String mensagem, String titulo){        
        String retorno;
        boolean num = false;
        do{
            num = true;
            retorno = JOptionPane.showInputDialog(null, mensagem, titulo, JOptionPane.PLAIN_MESSAGE);
            try{
                Integer.parseInt(retorno);
                
            }catch (NumberFormatException nfe){
                num = false;
            }
            
        } while ((retorno == null) || !num);
    
        return Integer.parseInt(retorno);
    }  
    
    /**
     * 
     * @return uma lista com todos os usuários artista cadastrados no sistema
     */
    public static ArrayList<Artista> getArtistasDoSistema(){
        ArrayList<Artista> artistasDoSistema = new ArrayList();
        
        Iterator<Usuario> it = usuariosDoSistema.iterator();
        while(it.hasNext()){                
            Usuario user = it.next();                
            if (user instanceof Artista){
                artistasDoSistema.add((Artista)user);
            }
        }
        return artistasDoSistema;
    }
    /**
     * 
     * @return lista de todas as músicas cadastradas no sistema
     */
    public static ArrayList<Musica> getMusicasDoSistema() {
        
        //usuariosDoSistema;
        ArrayList<Musica> musicasDoSistema = new ArrayList();
        Iterator<Artista> it = getArtistasDoSistema().iterator();
        while(it.hasNext()){                
            Artista user = it.next();      
            musicasDoSistema.addAll(user.getMusicas());
        }        
        return musicasDoSistema;
    }
    
    /**
     * Permite para por músicas no sistema, o campo de pesquisa é comparado, de forma
     * case-insensitive a: nome da música, nome do autor da música, tags de pesquisa do autor da música e
     * nome, ano de lançamento e gênero de cada álbum que contenha a música;
     * @param pesquisa texto base para realizar a pesquisa
     * @return Lista de músicas que se enquadrem na pesquisa realizada
     */
    public static ArrayList<Musica> pesquisarMusicas(String pesquisa){
        ArrayList<Musica> musicas = new ArrayList();
                
        Iterator<Musica> it = Controle.getMusicasDoSistema().iterator();        
        while(it.hasNext())
        {
            Musica musica = it.next();
            
            if (musica.getTitulo().toLowerCase().contains(pesquisa.toLowerCase()) || // Pesquisa por Titulo da Musica 
                musica.getArtista().getNomeArtistico().toLowerCase().contains(pesquisa.toLowerCase())) // Pesquisa por Nome do Artista
                musicas.add(musica); 
            else {
                boolean inserido = false;
                
                Iterator<Album> it2 = musica.getAlbuns().iterator();        
                while(it2.hasNext()){
                    Album album = it2.next();
                    if((isInteger(pesquisa) && album.getAno()==(Integer.parseInt(pesquisa))) || // Pesquisa por Ano do Album
                       album.getTitulo().toLowerCase().contains(pesquisa.toLowerCase()) || //Pesquisa por Titulo do Album
                       album.getGenero().toLowerCase().contains(pesquisa.toLowerCase()) //Pesquisa por Genero do Album
                    ){
                        musicas.add(musica);
                        inserido = true;
                    }
                }
                
                if (!inserido){                    
                    Iterator<String> it3 = musica.getArtista().getTags().iterator();        
                    while(it3.hasNext()){
                        String tag = it3.next();
                        if(tag.toLowerCase().contains(pesquisa.toLowerCase())){ //Pesquisa por Tag do Artista
                            musicas.add(musica);
                        }
                    }
                }
            }
        }
        
        return musicas;        
    }
    
    /**
     * Persiste os usuários cadastrados no sistema num arquivo padrão dados.dat
     */
    public static void gravarArquivo() {
        gravarArquivo("dados.dat", usuariosDoSistema);
    }

    /**
     * Persiste informações quaisquer em um arquivo quaisquer
     * @param nome nome do arquivo em que serão gravados os dados
     * @param dados dados a serem persistidos no arquivo
     */
    public static void gravarArquivo(String nome, Object dados) {
        File file = new File(nome);
        try {
            if (file.exists()){
                //System.out.println("Salvando Dados em " + nome + "...");
                FileOutputStream fout = new FileOutputStream(file);
                ObjectOutputStream oout = new ObjectOutputStream(fout);
                oout.writeObject(dados);
                fout.close();               
            }else{
                //System.out.println("Criando Arquivo em " + nome + "...");
                file.createNewFile();
            }
        } catch (IOException ioe) {
            System.out.println(ioe);
        }
    }
    
    /**
     * Obtem os dados apartir de um arquivo. Caso o arquivo não exista, ele é criado
     * @param nome nome do arquivo apartir do qual os dados serão criados
     * @return 
     */
    public static Object lerArquivo(String nome) {
        File file = new File(nome);
        Object retorno = null;
        try {
            if (file.exists()){
                System.out.println("Arquivo já existe");
                FileInputStream fin = new FileInputStream(file);
                ObjectInputStream oin = new ObjectInputStream(fin);
                retorno = oin.readObject();
                fin.close();   
                return retorno;
            }else{
                System.out.println("Arquivo sendo criado");
                file.createNewFile();                
                return new ArrayList();
            }
        } catch (IOException ioe) {
            System.out.println(ioe);
        } catch (ClassNotFoundException cnfe) {
            System.out.println(cnfe);
        }
        return null;
    }        
    
    /**
     * 
     * @return lista de funcionalidade que um usuário pode acessar dentro do sistema, de acordo com as permissões do mesmo (Artista, Usuário ou Visitante).
     */
    public static ArrayList<Object> getMenu(){
        ArrayList<Object> listaOpcoes;
        
        if (usuarioAtual instanceof Artista){
            Object[] opcoes = { "2 | Pesquisar Músicas", "3 | Creditar Conta", "4 | Comprar Música",
                                "5 | Criar Playlist", "6 | Gerenciar Playlist", "7 | Ver Playlist", 
                                "8 | Baixar Música", "11 | Gerenciar Perfil de Artista", "12 | Criar Álbum",
                                "13 | Gerenciar Álbum", "14 | Criar Música", "15 | Debitar Saldo",
                                "19 | Imprimir Informações", "20 | Sair"};                                       
            
            listaOpcoes = new ArrayList(Arrays.asList(opcoes));                    

        } else if(usuarioAtual instanceof Usuario){            
            //String             
            Object[] opcoes = {"2 | Pesquisar Músicas", "3 | Creditar Conta", "4 | Comprar Música",
                                "5 | Criar Playlist", "6 | Gerenciar Playlist", "7 | Ver Playlist", 
                                "8 | Baixar Música", "9 | Tornar-se Artista", "19 | Imprimir Informações", 
                                "20 | Sair"};
            listaOpcoes = new ArrayList(Arrays.asList(opcoes));
        } else {                                      
            Object[] opcoes = {"0 | Entrar", "1 | Cadastre-se", "2 | Pesquisar Músicas", "19 | Imprimir Informações"};
            listaOpcoes = new ArrayList(Arrays.asList(opcoes));
        }        
        return listaOpcoes;    
    }; 
    
}
